// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`issue-598.js 1`] = `
/* @flow */

type F<A> = { foo<B>(x: A): F<B> }
declare function foo(x: any): F<any>;
({ foo }: F<any>);

function bar(y: F<number>): F<string> { return y; }
function bar1<X>(y: F<X>): F<any> { return y; }
function bar2<X>(y: F<any>): F<X> { return y; }

type Functor<A> = {
  map<B>(f: (val: A) => B): Functor<B>
}

function identity<A>(val: A): Functor<A> {
  return {
    map<B>(f: (_: typeof val) => B): Functor<B> { return identity(f(val)) }
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */

type F<A> = { foo<B>(x: A): F<B> };
declare function foo(x: any): F<any>;
({ foo }: F<any>);

function bar(y: F<number>): F<string> {
  return y;
}
function bar1<X>(y: F<X>): F<any> {
  return y;
}
function bar2<X>(y: F<any>): F<X> {
  return y;
}

type Functor<A> = {
  map<B>(f: (val: A) => B): Functor<B>
};

function identity<A>(val: A): Functor<A> {
  return {
    map<B>(f: (_: typeof val) => B): Functor<B> {
      return identity(f(val));
    }
  };
}

`;

exports[`issue-1228.js 1`] = `
/* @flow */

type Task <error, value>
  = { chain<tagged>(next:(input:value) => Task<error, tagged>):
          Task<error, tagged>
    }

function id(x: Task<any,any>): Task<any,any> { return x; }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */

type Task<error, value> = {
  chain<tagged>(
    next: (input: value) => Task<error, tagged>
  ): Task<error, tagged>
};

function id(x: Task<any, any>): Task<any, any> {
  return x;
}

`;

exports[`test.js 1`] = `
class P<X> { x: X; } // this is like Promise

type Pstar<X> = X | Pstar<P<X>>; // this is like Promise*

var p: P<number> = new P;
(p.x: string); // error

var pstar: Pstar<number> = 0; // OK
(pstar: number); // error, but limit potentially unbounded number of errors!
                 // e.g., P<number> ~/~ number, P<P<number>> ~/~ number, ...

pstar = p; // OK
(pstar.x: string); // error

pstar = (new P: P<P<number>>); // OK
(pstar.x: string); // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class P<X> {
  x: X;
} // this is like Promise

type Pstar<X> = X | Pstar<P<X>>; // this is like Promise*

var p: P<number> = new P();
(p.x: string); // error

var pstar: Pstar<number> = 0; // OK
(pstar: number); // error, but limit potentially unbounded number of errors!
// e.g., P<number> ~/~ number, P<P<number>> ~/~ number, ...

pstar = p; // OK
(pstar.x: string); // error

pstar = (new P(): P<P<number>>); // OK
(pstar.x: string); // error

`;

exports[`test2.js 1`] = `
var a = []; // Array<X> ~> a
function bar() {
  a = a.concat([]); // terminate despite expanding types:
  // a ~> .concat(Array<Y>)
  // Array<X> ~> .concat(Array<Y>)
  // Array<X|Y> ~> a
  // Array<X|Y> ~> .concat(Array<Y>)
  // Array<X|Y|Y> ~> a
};

class A<X> {
  x: A<A<X>>;
}
var a_ = new A;
function foo0() {
  a_ = a_.x; // terminate despite expanding types
}

type T<X> = { y: S<X> };
type S<X> = T<S<X>>;
function foo1(b: S<*>) {
  b = b.y; // terminate despite expanding types, OK
  // S<*> = { y: S<S<*>> }
  // Both S<S<*>> and S<*> expand to { y: { y: ... }}.
}

class D<X> { }
class B<X> extends D<X> { }
class C<X> extends B<X> { }
((new C: C<number>): D<string>) // error: number ~/~ string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var a = []; // Array<X> ~> a
function bar() {
  a = a.concat([]); // terminate despite expanding types:
  // a ~> .concat(Array<Y>)
  // Array<X> ~> .concat(Array<Y>)
  // Array<X|Y> ~> a
  // Array<X|Y> ~> .concat(Array<Y>)
  // Array<X|Y|Y> ~> a
}

class A<X> {
  x: A<A<X>>;
}
var a_ = new A();
function foo0() {
  a_ = a_.x; // terminate despite expanding types
}

type T<X> = { y: S<X> };
type S<X> = T<S<X>>;
function foo1(b: S<*>) {
  b = b.y; // terminate despite expanding types, OK
  // S<*> = { y: S<S<*>> }
  // Both S<S<*>> and S<*> expand to { y: { y: ... }}.
}

class D<X> {}
class B<X> extends D<X> {}
class C<X> extends B<X> {}
((new C(): C<number>): D<string>); // error: number ~/~ string

`;

exports[`test3.js 1`] = `
type I<X> = () => I<I<X>>;
type J<X> = () => J<J<X>>;

function foo(x: I<number>): J<number> {
  return x; // terminate despite expanding types, OK
  // I<number> and J<number> both expand to () => () => ...
}

type Q<X> = { x: X; }
type P<X> = () => Q<P<X>>;

function bar(x: P<number>): () => P<number> {
  return x; // terminate despite expanding types, error
  // P<number> = () => { x: P<number> }
  // () => P<number> = () => () => { x: P<number> }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type I<X> = () => I<I<X>>;
type J<X> = () => J<J<X>>;

function foo(x: I<number>): J<number> {
  return x; // terminate despite expanding types, OK
  // I<number> and J<number> both expand to () => () => ...
}

type Q<X> = { x: X };
type P<X> = () => Q<P<X>>;

function bar(x: P<number>): () => P<number> {
  return x; // terminate despite expanding types, error
  // P<number> = () => { x: P<number> }
  // () => P<number> = () => () => { x: P<number> }
}

`;

exports[`test4.js 1`] = `
type T = T // cycle in type alias should not cause non-termination
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type T = T; // cycle in type alias should not cause non-termination

`;

exports[`test5.js 1`] = `
/* @flow */

type NestedArray<T> = Array<T | NestedArray<T>>;

function flatten<T>(arrArg: NestedArray<T>) {
  let arr = arrArg;
  while (true) {
    arr = Array.prototype.concat.apply([], arr);
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */

type NestedArray<T> = Array<T | NestedArray<T>>;

function flatten<T>(arrArg: NestedArray<T>) {
  let arr = arrArg;
  while (true) {
    arr = Array.prototype.concat.apply([], arr);
  }
}

`;
